package org.robot.scm.platform.registry;

import static java.lang.Runtime.getRuntime;

import com.google.common.collect.Maps;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.robot.scm.platform.AbstractMonitor;
import org.robot.scm.platform.AbstractRegistry;
import org.robot.scm.platform.server.ScmHttpServer;
import org.robot.scm.pojos.config.BaseConfig;
import org.robot.scm.pojos.enums.PlatformEnum;
import org.robot.scm.pojos.platform.server.SshMySql;

/**
 * @Author : Awn create on 2024/5/12 19:36
 */
@Slf4j
public class SessionRegistry extends AbstractRegistry {

    @Getter
    private static final Map<String, Session> sessionMap = Maps.newHashMap();

    @Override
    public int getOrder() {
        return 1;
    }

    @Override
    public void registry() {
        if (!AbstractMonitor.mainConfig.getEnables().contains(PlatformEnum.SQL.getVal())) {
            return;
        }
        try {
            BaseConfig config = ScmHttpServer.getTargetConfig(PlatformEnum.SQL);
            List<SshMySql> sshMySqls = config.getCurrentPlatform().getSshMysqlDetails();
            for (SshMySql mySql : sshMySqls) {
                sessionMap.put(mySql.getName(), initSession(mySql));
                log.info("init tunneling {} ... ok", mySql.getName());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        getRuntime().addShutdownHook(new Thread(() -> {
            if (CollectionUtils.isNotEmpty(sessionMap.values())) {
                sessionMap.values().forEach(Session::disconnect);
                log.info("close {} tunneling ... ok", sessionMap.size());
            }
        }));
    }

    /**
     * 建立远程隧道 返回本地到远程的端口转发
     */
    private static Session initSession(SshMySql config) throws JSchException {
        JSch jsch = new JSch();
        if (StringUtils.isBlank(config.getSshPwd())) {
            if (StringUtils.isNotBlank(config.getPrvPass())) {
                jsch.addIdentity(config.getPrvKey(), config.getPrvPass());
            } else {
                jsch.addIdentity(config.getPrvKey());
            }
        }
        Properties properties = new Properties();
        properties.put("StrictHostKeyChecking", "no");
        properties.put("ServerAliveInterval", "10000"); // 设置心跳间隔，单位为毫秒，这里是10秒
        properties.put("ServerAliveCountMax", "5"); // 设置心跳未响应的最大次数，超过这个次数则认为连接断开
        if (StringUtils.isBlank(config.getSshPwd())) {
            Session session = jsch.getSession(config.getSshUser(), config.getSshHost(), config.getSshPort());
            session.setConfig(properties);
            session.connect(10000);
            return session;
        }
        Session session = jsch.getSession(config.getSshUser(), config.getSshHost(), config.getSshPort());
        session.setPassword(config.getSshPwd());
        session.setConfig(properties);
        session.connect(10000);
        return session;
    }

}
